﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using SMA.GENTEv1.Dados;

namespace SMA.GENTEv1
{
    public class CategoriaCNH
    {
        #region Variaveis Membro
        private int _idCategoriaCNH;
        private string _categoria;
        private string _descricao;
        private GENTEEntities _context;
        #endregion

        #region Parametros
        public int IdCategoriaCNH
        {
            get { return _idCategoriaCNH; }
            set { _idCategoriaCNH = value; }
        }

        public string Categoria
        {
            get { return _categoria; }
            set { _categoria = value; }
        }

        public string Descricao
        {
            get { return _descricao; }
            set { _descricao = value; }
        }
        #endregion

        #region Contrutores
        public CategoriaCNH()
        {
            _context = new GENTEEntities();
        }

        public CategoriaCNH(int _idcategoriaCNH, bool _carregaDados)
        {
            _context = new GENTEEntities();
            if (!_carregaDados)
                this._idCategoriaCNH = _idcategoriaCNH;
            else
                Carregar(_idcategoriaCNH);
        }
        #endregion

        #region Métodos Privados
        private static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
        {
            if (null == valueSelector)
            {
                throw new
                    ArgumentNullException("valueSelector");
            }
            if (null == values) { throw new ArgumentNullException("values"); }

            ParameterExpression p = valueSelector.Parameters.Single();
            if (!values.Any())
            {
                return e => false;
            }

            var equals = values.Select(value =>
            (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value,
            typeof(TValue))));
            var body = equals.Aggregate<Expression>((accumulate, equal) =>
            Expression.Or(accumulate, equal));
            return Expression.Lambda<Func<TElement, bool>>(body, p);
        }

        public void Carregar(int _idcategoriaCNH)
        {
            try
            {
                var consulta = (from categoriaCNH in _context.tab_categoria_cnh
                                where categoriaCNH.id_categoria_cnh == _idcategoriaCNH
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    this._idCategoriaCNH = list.id_categoria_cnh;
                    this._categoria = list.categoria;
                    this._descricao = list.descricao;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private bool VerificaCadastro()
        {
            try
            {
                bool verifica = false;

                if (this._categoria == string.Empty)
                    throw new Exception("É necessário informar a categoria!");

                if (this._descricao == string.Empty)
                    throw new Exception("É necessário informar a descrição!");

                if (this._idCategoriaCNH == 0)
                {
                    var consulta = (from categoria in _context.tab_categoria_cnh
                                    where (categoria.categoria == this._categoria)
                                    || (categoria.descricao == this._descricao)
                                    select new
                                    {
                                        categoria.id_categoria_cnh
                                    });

                    if (consulta.ToList().Count > 0)
                        throw new Exception("Foi encontrado uma Categoria de Habilitação conforme a categoria/descrição informados. Operação cancelada!");
                }

                verifica = true;
                return verifica;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private List<CategoriaCNH> SelectCategoriaModelo(int _idcategoria)
        {
            try
            {
                List<CategoriaCNH> listCategoria = new List<CategoriaCNH>();

                var consulta = (from categoriaCNH in _context.tab_categoria_cnh
                                join modelocategoriaCNH in _context.tab_frota_modelo_categoria_cnh on categoriaCNH.id_categoria_cnh equals modelocategoriaCNH.tab_categoria_cnh.id_categoria_cnh
                                where categoriaCNH.id_categoria_cnh == _idcategoria
                                select categoriaCNH).Distinct();

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoria = new CategoriaCNH();
                    categoria.IdCategoriaCNH = list.id_categoria_cnh;
                    categoria.Categoria = list.categoria;
                    categoria.Descricao = list.descricao;

                    listCategoria.Add(categoria);
                }

                return listCategoria;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private List<CategoriaCNH> SelectCategoriaClassificacao(int _idcategoria)
        {
            try
            {
                List<CategoriaCNH> listCategoria = new List<CategoriaCNH>();

                var consulta = (from categoriaCNH in _context.tab_categoria_cnh
                                join classificacaocategoriaCNH in _context.tab_frota_modelo_classificacao_categoria_cnh on categoriaCNH.id_categoria_cnh equals classificacaocategoriaCNH.tab_categoria_cnh.id_categoria_cnh
                                where categoriaCNH.id_categoria_cnh == _idcategoria
                                select categoriaCNH).Distinct();

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoria = new CategoriaCNH();
                    categoria.IdCategoriaCNH = list.id_categoria_cnh;
                    categoria.Categoria = list.categoria;
                    categoria.Descricao = list.descricao;

                    listCategoria.Add(categoria);
                }

                return listCategoria;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos Públicos

        #region Métodos de Seleção
        public List<CategoriaCNH> SelectAll()
        {
            try
            {
                List<CategoriaCNH> listCategoriaCNH = new List<CategoriaCNH>();

                var consulta = (from categoriaCNH in _context.tab_categoria_cnh
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoria = new CategoriaCNH();
                    categoria.IdCategoriaCNH = list.id_categoria_cnh;
                    categoria.Categoria = list.categoria;
                    categoria.Descricao = list.descricao;

                    listCategoriaCNH.Add(categoria);
                }

                return listCategoriaCNH;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<CategoriaCNH> SelectVeiculoCNH(int _idmodelo)
        {
            try
            {
                List<CategoriaCNH> listCategoriaCNH = new List<CategoriaCNH>();

                var consulta = (from modelocategoriaCNH in _context.tab_frota_modelo_categoria_cnh
                                join categoriaCNH in _context.tab_categoria_cnh on modelocategoriaCNH.tab_categoria_cnh.id_categoria_cnh equals categoriaCNH.id_categoria_cnh
                                where modelocategoriaCNH.tab_frota_modelo.id_frota_modelo == _idmodelo
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoriaCNH = new CategoriaCNH();
                    categoriaCNH.IdCategoriaCNH = list.id_categoria_cnh;
                    categoriaCNH.Categoria = list.categoria;
                    categoriaCNH.Descricao = list.descricao;

                    listCategoriaCNH.Add(categoriaCNH);
                }

                return listCategoriaCNH;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<CategoriaCNH> SelectClassificacaoCNH(int _idclassificacao)
        {
            try
            {
                List<CategoriaCNH> listCategoriaCNH = new List<CategoriaCNH>();

                var consulta = (from classificacaocategoriaCNH in _context.tab_frota_modelo_classificacao_categoria_cnh
                                join categoriaCNH in _context.tab_categoria_cnh on classificacaocategoriaCNH.tab_categoria_cnh.id_categoria_cnh equals categoriaCNH.id_categoria_cnh
                                where classificacaocategoriaCNH.tab_frota_modelo_classificacao.id_frota_modelo_classificacao == _idclassificacao
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoriaCNH = new CategoriaCNH();
                    categoriaCNH.IdCategoriaCNH = list.id_categoria_cnh;
                    categoriaCNH.Categoria = list.categoria;
                    categoriaCNH.Descricao = list.descricao;

                    listCategoriaCNH.Add(categoriaCNH);
                }

                return listCategoriaCNH;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<CategoriaCNH> SelectPor(int[] _idcategoriaCNH)
        {
            try
            {
                List<CategoriaCNH> listCategoria = new List<CategoriaCNH>();

                if (_idcategoriaCNH.Count() == 0)
                    throw new Exception("É necessário selecionar ao menos uma categoria de habilitação para efetuar a pesquisa!");

                var consulta = (from categoriaCNH in _context.tab_categoria_cnh.Where((BuildContainsExpression<tab_categoria_cnh, int>(item => item.id_categoria_cnh, _idcategoriaCNH)))
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    CategoriaCNH categoria = new CategoriaCNH();
                    categoria.IdCategoriaCNH = list.id_categoria_cnh;
                    categoria.Categoria = list.categoria;
                    categoria.Descricao = list.descricao;

                    listCategoria.Add(categoria);
                }

                return listCategoria;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region Métodos de Persistência
        public void Salvar()
        {
            try
            {
                if (VerificaCadastro())
                {
                    if (this._idCategoriaCNH == 0)
                    {
                        tab_categoria_cnh tabCategoriaCNH = new tab_categoria_cnh();
                        tabCategoriaCNH.categoria = this._categoria;
                        tabCategoriaCNH.descricao = this._descricao;

                        _context.AddTotab_categoria_cnh(tabCategoriaCNH);
                        _context.SaveChanges();
                    }
                    else
                    {
                        tab_categoria_cnh tabCategoriaCNH = (from categoriaCNH in _context.tab_categoria_cnh
                                                             where categoriaCNH.id_categoria_cnh == this._idCategoriaCNH
                                                             select categoriaCNH).First();

                        tabCategoriaCNH.categoria = this._categoria;
                        tabCategoriaCNH.descricao = this._descricao;

                        _context.SaveChanges();
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Excluir()
        {
            try
            {
                List<CategoriaCNH> listCategoria = new List<CategoriaCNH>();

                listCategoria = SelectCategoriaModelo(this._idCategoriaCNH);
                if (listCategoria.Count > 0)
                    throw new Exception("Não é possível excluir esta categoria pois existem veículos vinculados para a mesma. Operação cancelada!");

                listCategoria = SelectCategoriaClassificacao(this._idCategoriaCNH);
                if (listCategoria.Count > 0)
                    throw new Exception("Não é possível excluir esta categoria pois existem classificações vinculadas para a mesma. Operação cancelada!");

                PessoaDocCNH pessoaCNH = new PessoaDocCNH();
                List<PessoaDocCNH> listPessoaCNH = new List<PessoaDocCNH>();
                listPessoaCNH = pessoaCNH.SelectCNH(this._idCategoriaCNH);

                if (listPessoaCNH.Count > 0)
                    throw new Exception("Não é possível excluir esta categoria pois existem CNHs vinculadas para a mesma. Operação cancelada!");

                var consulta = (from categoriaCNH in _context.tab_categoria_cnh
                                where categoriaCNH.id_categoria_cnh == this._idCategoriaCNH
                                select categoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    _context.DeleteObject(list);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Excluir(int _idmodelo)
        {
            try
            {
                var consulta = (from modelocategoriaCNH in _context.tab_frota_modelo_categoria_cnh
                                where modelocategoriaCNH.tab_frota_modelo.id_frota_modelo == _idmodelo
                                select modelocategoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    _context.DeleteObject(list);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void ExcluirClassificacao(int _idclassificacao)
        {
            try
            {
                var consulta = (from classificacaocategoriaCNH in _context.tab_frota_modelo_classificacao_categoria_cnh
                                where classificacaocategoriaCNH.tab_frota_modelo_classificacao.id_frota_modelo_classificacao == _idclassificacao
                                select classificacaocategoriaCNH);

                var listConsulta = consulta.ToList();

                foreach (var list in listConsulta)
                {
                    _context.DeleteObject(list);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #endregion
    }
}
